//
// Copyright (c) 2005 BroadVision, Inc. All rights reserved.
//
// This software is copyrighted.  Under the copyright laws, this software
// may not be copied, in whole or in part, without prior written consent
// of BroadVision, Inc. or its assignees.  This software is provided under
// the terms of a license between BroadVision and the recipient, and its
// use is subject to the terms of that license.
//
// This software may be protected by one or more U.S. and International
// patents.  Certain applications of BroadVision One-To-One software are
// covered by U.S. patent 5,710,887.
//
// TRADEMARKS: BroadVision and BroadVision One-To-One are registered
// trademarks of BroadVision, Inc., in the United States and the European
// Community, and are trademarks of BroadVision, Inc., in other
// countries.  The BroadVision logo, is a trademark of BroadVision, Inc.,
// in the United States and other countries. Additionally, IONA and Orbix
// are trademarks of IONA Technologies, Ltd.  RSA, MD5, and RC2 are
// trademarks of RSA Data Security, Inc.
//

package com.broadvision.manage.common.tools.action.group;

import java.util.*;
import java.security.Principal;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.broadvision.data.client.DataManager;
import com.broadvision.web.util.ViewDynaBean;
import com.broadvision.system.accesscontrol.client.*;
import com.broadvision.visitor.client.Visitor;
import com.broadvision.visitor.client.VisitorGroupManager;
import com.broadvision.visitor.client.VisitorContext;
import com.broadvision.visitor.utils.GroupContextParser;
import com.broadvision.visitor.interfaces.VisitorGroup;
import com.broadvision.portal.services.*;

import com.broadvision.manage.tools.action.BaseAction;
import com.broadvision.manage.common.tools.action.user.UserUtils;

/**
 * Searches subgroups.
 */
public class GroupPopupSearchAction extends BaseAction {

  public static final String VIEW_BEAN_NAME = "mtGroupPopupView";
  public static final String DTO_BEAN_NAME  = "mtGroupPopupDTO";

  /**
   * Implements the action for searching groups with group name.
   * <p> <p>
   * @param mapping <code>ActionMapping</code> object used to select this instance
   * @param form Optional <code>ActionForm</code> bean for this request (if any)
   * @param request <code>HttpServletRequest</code> object to process
   * @param response <code>HttpServletResponse</code> object to process
   * <p> <p>
   * @return <code>ActionForward</code> instance describing where and how
   * control should be forwarded, or null if the response has already been completed
   * <p> <p>
   * @throws Exception if an error occurs
   */
  public ActionForward processExecute(ActionMapping mapping,
                                      ActionForm form,
                                      HttpServletRequest request,
                                      HttpServletResponse response)
                               throws Exception
  {
    try {
      ViewDynaBean view = new ViewDynaBean(VIEW_BEAN_NAME, mapping);
      request.setAttribute(VIEW_BEAN_NAME, view);
      boolean doSearch = ((Boolean) UserUtils.getP(form, "executeSearch")).booleanValue();
      if (doSearch) {
        // search sub groups
        String groupFQN = (String) UserUtils.getP(form, "groupFQN");
        prepareGroupViewBean(groupFQN, mapping, form, view, request);
      }
      UserUtils.setP(form, "groupFQN", "root");
    }
    catch (Exception ex) {
      ex.printStackTrace();
      return mapping.findForward("failure");
    }
    return mapping.findForward("success");
  }

  /**
   * Private method to prepare the view beans for a group search
   */
  private void prepareGroupViewBean(String groupFQN,
				    ActionMapping mapping,
				    ActionForm form,
				    ViewDynaBean view,
				    HttpServletRequest request) throws Exception 
  {
    String searchStr = (String)UserUtils.getP(form, "groupName");
    if (!UserUtils.isEmptyString(searchStr)) {
      searchStr = "%" + searchStr.trim() + "%";
    }
    long maxNumber = 200;
    VisitorGroup[] groups = null;
    PortalVisitor agent = getPortalVisitor(request);
    Visitor visitor = agent.getVisitor();
    boolean userAdmin = isUserInRole(visitor, "UserAdmin");
    List orgAdmins = null;
    
    // Find the FQN for defaultCtx
    String defaultCxt = GroupContextParser.getDefaultNamingContextName();
    VisitorGroupManager vGroupMgr = new VisitorGroupManager(defaultCxt);  
    VisitorGroup rootGroup = vGroupMgr.getRootVisitorGroup();
    String FQN = rootGroup.getFullyQualifiedName();

    // Retrieve serviceId
    VisitorContext vc = agent.getContext();
    int serviceId = vc.getServiceId();
 
    if (!userAdmin) {
      // non user admin
      AccessManager accessMgr = AccessManager.instance();
      orgAdmins = accessMgr.getOwnerObjectsForPrincipal((Principal)visitor, "OrganizationAdmin");
      if ((null != orgAdmins) && (orgAdmins.size() > 0)) {
        // org admin
        VisitorGroup[][] tmpGroups = new VisitorGroup[orgAdmins.size()][];
        int totalLength = 0;
        int i = 0;
        for (Iterator it = orgAdmins.iterator(); it.hasNext(); ) {
          ACObjectID ac = (ACObjectID) it.next();
          VisitorGroup thisGroup = VisitorGroupManager.getVisitorGroupByFqn(ac.getObjectID());
          /**
           * finds VisitorGroups by substring query.
           * @param subStr is the substring to be searched for in a group name
           * @param maxNumber is the maximum number of results to be retrieved
           * @return VisitorGroup array
           * @throws VisitorGroupException
           */
          VisitorGroup[] oneGroup = thisGroup.findVisitorGroupsBySubstring(searchStr, (int) maxNumber);
          totalLength += oneGroup.length;
          tmpGroups[i++] = oneGroup;
        }
        groups = new VisitorGroup[totalLength];
        int j = 0;
        for (i = 0; i < orgAdmins.size(); i++) {
          for (int k  = 0; k < tmpGroups[i].length; k++) {
            groups[j] = tmpGroups[i][k]; 
            j++;
          }
        }
      }
      else {
        //request.setAttribute(Globals.ERROR_KEY, "error.group.noGroupAdmin");
        //return mapping.findForward("failure");
        // quietly return
      }
    }
    else {
      // user admin
      groups = VisitorGroupManager.findVisitorGroupsBySubstring((int) serviceId, searchStr, (int) maxNumber);
    }
    
    int numOfGroups = ((null == groups) ? 0 : groups.length);
    // pagination support
    int countOfResults = numOfGroups;
    // entriesPerPage is always not null
    int entriesPerPage = ((Integer) UserUtils.getP(form, "entriesPerPage")).intValue();
    int firstEntry = 0;
    int lastEntry = countOfResults;
    int totalPageNumber = 1;
    int currentPageNumber = 1;
    if (countOfResults > entriesPerPage) {
      // currentPageNumber and totalPageNumber are always not null
      currentPageNumber = ((Integer) UserUtils.getP(form, "currentPageNumber")).intValue();
      totalPageNumber = countOfResults / entriesPerPage;
      if (countOfResults % entriesPerPage > 0) {
        totalPageNumber++;
      }
      // if the entriesPerPage has been increased
      if (currentPageNumber > totalPageNumber) {
        currentPageNumber = totalPageNumber;
      }
      if (currentPageNumber == 0) {
        // first page
        currentPageNumber = 1;
      }
      else {
        firstEntry = (currentPageNumber - 1) * entriesPerPage;
      }
      lastEntry = firstEntry + entriesPerPage;
    }
    else {
      entriesPerPage = countOfResults;
    }
    UserUtils.setP(form, "currentPageNumber", new Integer(currentPageNumber));
    UserUtils.setP(form, "totalPageNumber", new Integer(totalPageNumber));
    List dtos = new ArrayList(entriesPerPage);
    UserUtils.setP(view, "groupList", dtos);
    UserUtils.setP(view, "numOfGroups", new Long(numOfGroups));
    for (int i = firstEntry; (i < countOfResults) && (i < lastEntry); i++) {
      VisitorGroup g = groups[i];
      ViewDynaBean oneDto = new ViewDynaBean(DTO_BEAN_NAME, mapping);
      UserUtils.setP(oneDto, "name", g.getFriendlyName());	
      UserUtils.setP(oneDto, "fqn", g.getFullyQualifiedName());		
      dtos.add(oneDto);
    } // end of for ... loop
    // breadcrumb support
    HashMap orgAdminGroups = new HashMap();
    if (orgAdmins != null) {
      for (Iterator it = orgAdmins.iterator(); it.hasNext(); ) {
        ACObjectID ac = (ACObjectID)it.next();
        orgAdminGroups.put(ac.getObjectID(), ac);
      }
    }
    List breadcrumbs = new ArrayList();
    ViewDynaBean oneDto = new ViewDynaBean(DTO_BEAN_NAME, mapping);
    
//    UserUtils.setP(oneDto, "name", getResources(request, "mt.messages").getMessage(getLocale(request), "mt.group.label.root"));
    String portalRoot = getPortalRootNameFromFQN(FQN);
    UserUtils.setP(oneDto, "name",portalRoot);
    UserUtils.setP(oneDto, "fqn", "root");
    breadcrumbs.add(oneDto);
    UserUtils.setP(view, "breadcrumbs", breadcrumbs);
    UserUtils.setP(view, "groupName", getResources(request, "mt.messages").getMessage(getLocale(request), "mt.group.label.root"));
  }

  private String getPortalRootNameFromFQN(String name) {
    int i = name.lastIndexOf("/");
    if (i < 0) {
      return name;
    }
    else{
      StringTokenizer st = new StringTokenizer(name, "/");
      st.nextToken();
      return st.nextToken();
    }
  }

}
